package org.example.maven.controller;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.example.maven.annotation.ReadOnlyMode;
import org.example.maven.annotation.logAnnotation;
import org.example.maven.common.RedisCommon;
import org.example.maven.pojo.Result;
import org.example.maven.pojo.user.Login.LoginRequest;
import org.example.maven.pojo.user.UserDetailsImpl;
import org.example.maven.pojo.user.list.AddUser;
import org.example.maven.pojo.user.list.SearchUser;
import org.example.maven.pojo.user.person.PersonDetails;
import org.example.maven.pojo.user.person.PersonUpdatePassword;
import org.example.maven.pojo.utils.Ids;
import org.example.maven.service.UserService;
import org.example.maven.utils.JwtUtils;
import org.example.maven.utils.ThreadlocalUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.AuthenticationManager;

import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@RestController
@CrossOrigin
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userServiceImpl;
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private RedisCommon redisCommon;

    @PostMapping("/login")
    //用户登录
    @PreAuthorize("permitAll()")
    public Result login(@RequestBody LoginRequest loginRequest){
        System.out.println("传递的uuid："+loginRequest.getUuid()+"传递的code："+loginRequest.getCode());
        if(redisCommon.checkCodeIsTure(loginRequest.getUuid(),loginRequest.getCode())){
            try {
                Authentication authentication = authenticationManager.authenticate(
                        new UsernamePasswordAuthenticationToken(
                                loginRequest.getUsername(),
                                loginRequest.getPassword()
                        )
                );
                SecurityContextHolder.getContext().setAuthentication(authentication);
                UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal();
                Map<String, Object> claims = new HashMap<>();
                claims.put("id", userDetails.getUser().getId());
                claims.put("username", userDetails.getUser().getUsername());
                String jwt = JwtUtils.getUserJwt(claims);
                redisCommon.setCacheObject(jwt, jwt, 60, TimeUnit.MINUTES);
                System.out.println(userDetails.getAuthorities());
                return Result.success("登录成功", jwt);
            } catch (BadCredentialsException e) {
                return Result.error("账号或者密码错误");
            }
        }
        else {
            return Result.error("验证码错误");
        }
    }

    //退出登录
    @PostMapping("/loginOut")
    @PreAuthorize("permitAll()")
    public Result userLoginOut(){
        Authentication authentication=SecurityContextHolder.getContext().getAuthentication();
        authentication.getPrincipal();
        return Result.success("退出成功");
    }

    @GetMapping
    //获取用户的listTable信息
    @PreAuthorize("hasAnyAuthority('user:manage')")
    public Result getAllUserList(@RequestParam("pageNum") Integer pageNum,@RequestParam("pageSize") Integer pageSize){
        Result result=Result.success();
        result.put("data",userServiceImpl.getAllUserList(pageNum,pageSize));
        result.put("total",userServiceImpl.getUserCount(new SearchUser()));
        return result;
    }

    //获取用户select的选项信息
    @GetMapping("/getUserManagementSelect")
    @PreAuthorize("permitAll()")
    public Result getUserManagementSelect(){
        return Result.success(userServiceImpl.getUserManagementSelect());
    }

    @PostMapping("/addUser")
    @PreAuthorize("hasAnyAuthority('user:manage')")
    @logAnnotation(
            type = "新增",
            detail = "新增用户{#addUser.username}"
    )
    @ReadOnlyMode
    public Result addUser(@RequestBody AddUser addUser){
        userServiceImpl.addUser(addUser);
        return Result.success();
    }

    @GetMapping("/getEditUser")
    @PreAuthorize("hasAnyAuthority('user:manage')")
    //获取待编辑的用户信息
    public Result getEditUser(@RequestParam("id") Integer id){
        AddUser addUser=new AddUser();
        addUser=userServiceImpl.getEditUser(id);
        addUser.setRoleId(userServiceImpl.getUserRole(id));
        return Result.success(addUser);
    }

    @PutMapping
    @ReadOnlyMode
    @PreAuthorize("hasAnyAuthority('user:manage')")
    @logAnnotation(
            type = "更新",
            detail = "更新用户{#addUser.username}"
    )
    //更新用户信息
    public Result updateUser(@RequestBody AddUser addUser){
        userServiceImpl.updateUser(addUser);
        return Result.success();
    }

    @PatchMapping
    @ReadOnlyMode
    @PreAuthorize("hasAnyAuthority('user:manage')")
    @logAnnotation(
            type = "删除",
            detail = "删除用户"
    )
    //删除用户
    public Result deleteUser(@RequestBody  Ids ids){
        userServiceImpl.deleteUser(ids.getId());
        return Result.success();
    }

    @GetMapping("/getSpecieUser")
    @PreAuthorize("hasAnyAuthority('user:manage')")
    //获取特定的用户信息
    public Result getSpecieUser(SearchUser searchUser,@RequestParam("pageNum") Integer pageNum,@RequestParam("pageSize") Integer pageSize){
        Result result=Result.success();
        result.put("data",userServiceImpl.getSpecieUser(searchUser,pageNum,pageSize));
        result.put("total",userServiceImpl.getUserCount(searchUser));
        return result;
    }

    @GetMapping("/getPersonalDetails")
    @PreAuthorize("permitAll()")
    //获取个人中心的个人信息
    public Result getPersonalDetails(){
        String username=JwtUtils.getJwtUsername(ThreadlocalUtils.get());
        return Result.success(userServiceImpl.getPersonalDetails(username));
    }
    @PutMapping("/updatePersonalDetails")
    @ReadOnlyMode
    @PreAuthorize("hasAnyAuthority('user:manage')")
    @logAnnotation(
            type = "更新",
            detail = "更新用户{#personDetails.username}的个人信息"
    )
    public Result updatePersonalDetails(@RequestBody PersonDetails personDetails){
        userServiceImpl.updatePersonDetails(personDetails);
        return Result.success("修改信息成功");
    }
    @PutMapping("/updateUserPassword")
    @PreAuthorize("hasAnyAuthority('user:manage')")
    @logAnnotation(
            type = "更新",
            detail = "更新用户id为{#personUpdatePassword.id}的密码"
    )
    //更新用户的密码
    public Result updateUserPassword(@RequestBody PersonUpdatePassword personUpdatePassword){
        userServiceImpl.updatePersonPassword(personUpdatePassword);
        return Result.success("修改成功");
    }
    @PutMapping("/updatePersonPassword")
    @PreAuthorize("permitAll()")
    @logAnnotation(
            type = "更新",
            detail = "更新用户id为{#personUpdatePassword.id}的密码"
    )
    //修改个人信息的密码
    //@ReadOnlyMode
    public Result updatePersonPassword(@RequestBody PersonUpdatePassword personUpdatePassword){
        String selectPassword=userServiceImpl.getPasswordById(personUpdatePassword.getId());
        if(selectPassword.equals(personUpdatePassword.getOldPassword())){
            if(personUpdatePassword.getNewPassword().equals(personUpdatePassword.getOldPassword())){
                return Result.error(408,"新密码不能与旧密码一致");
            }else {
                userServiceImpl.updatePersonPassword(personUpdatePassword);
                Authentication authentication=SecurityContextHolder.getContext().getAuthentication();
                authentication.getPrincipal();
                redisCommon.deleteDataByKey(ThreadlocalUtils.get());
                return Result.success("修改成功");
            }
        }else {
            return Result.error(407,"原密码输入错误");
        }
    }
}
